﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Profiling;
using Yoozoo.Framework.Core;
using Yoozoo.Managers.ResourceManagerV2.Runtime;

namespace MouthAnimationFrame
{
    /// <summary>
    /// 口型动画状态
    /// </summary>
    public enum MouthAnimStatus
    {
        Stop,
        Playing,
        Pause,
    }

    /// <summary>
    /// 口型管理
    /// 入口方法: 
    /// PlayMouthEvent(Animator,eventName) ： Animator: 对应模型的口型Animator,eventName,对应wwise音频的EventName
    /// 由Animaor进入后,会在对应Animator下挂一个MouthAnimation脚本,
    /// 然后会在管理器中建立映射关系,如果有映射,直接MouthAnimation引用,没有的话
    /// 
    /// 几个问题,是否需要限制最大播放数量(是的话,是交给子节点控制,还是交给Mgr控制)
    /// </summary>
    public class MouthAnimationSyncHelper : SingletonMono<MouthAnimationSyncHelper>
    {

        #region 参数部分
        const string animConfigPath = "Assets/ResourcesAssets/Config/SoundShape/LC_Mouth.txt";

        /// <summary>
        /// 初始化完毕
        /// </summary>
        public bool IsReady { get; private set; } = false;
        //根据导出的配置文件获得的口型数据
        private Dictionary<string, string> m_AudioMouthDic = new Dictionary<string, string>();

        public int mLipSynchAnimStateId;
        //停止口型的动画过渡
        public int mLipStopAnimStateId;

        public List<int> mLipSyncAnimStateNameList = new List<int>();

        /// <summary>
        /// Animator与MouthAnimation组件的映射
        /// </summary>
        private Dictionary<Animator, MouthAnimation> mouthAnimMapper = new Dictionary<Animator, MouthAnimation>();
        #endregion

        #region 工具生命周期


        public override void Initialize(Options options = null)
        {
            base.Initialize(options);
            //加载口型数据
            m_AudioMouthDic.Clear();

            UMTResource.LoadAssetRapid(animConfigPath, (assetName, asset, duration, data) =>
            {
                if (asset is TextAsset text)
                {
                    //加载成功
                    Profiler.BeginSample("MouthAnimationSyncHelper.Initialize");
                    string[] textRows = text.ToString().Split(Environment.NewLine.ToCharArray());
                    for (int i = 0; i < textRows.Length; i++)
                    {
                        if (textRows[i].Length > 0)
                        {
                            try
                            {
                                //已知问题,LC_Mouth.txt里可能存在空行,导致这里报错,但是Windows没问题...(?
                                string[] t = textRows[i].Split(':');
                                if (t.Length == 2)
                                {
                                    m_AudioMouthDic[t[0]] = t[1];
                                }
                            }
                            catch (Exception e)
                            {
                                //
                            }
                        }
                    }
                    Profiler.EndSample();

                    IsReady = true;
                    UMTResource.UnloadAsset(asset);
                }
                else
                {
                    //加载失败
                    Debug.LogError("口型匹配文件加载失败,请检查配置资源文件是否存在: " + animConfigPath);
                }
            });

            mLipSynchAnimStateId = Animator.StringToHash("lipSynch");
            mLipStopAnimStateId = Animator.StringToHash("lipStop");
            for (int i = 0; i <= 6; i++)
            {
                mLipSyncAnimStateNameList.Add(Animator.StringToHash("kouxing0" + (i + 1).ToString()));
            }
        }

        public override void Dispose()
        {
            base.Dispose();
        }

        #endregion

        #region Unity生命周期
        private void OnDestroy()
        {

            m_AudioMouthDic.Clear();
        }
        #endregion

        #region 组件流程操作
        /// <summary>
        /// 反向注册,Mono控制组件随物体创建与销毁
        /// 引用负责全局管理
        /// </summary>
        /// <param name="mouthAnim"></param>
        public void RegisterMouthComponent(MouthAnimation mouthAnim)
        {
            if(mouthAnim != null && mouthAnim.mHeadAnimator != null)
            {
                if (mouthAnimMapper.ContainsKey(mouthAnim.mHeadAnimator))
                {
                    mouthAnimMapper[mouthAnim.mHeadAnimator] = mouthAnim;
                }else
                {
                    mouthAnimMapper.Add(mouthAnim.mHeadAnimator, mouthAnim);
                }
            }
            else
            {
                Debug.LogError("MouthAnimation: 请确认传入MouthAnimation中配置正确");
            }
        }

        public void DisposeMouthComponent(MouthAnimation anim)
        {
            if(anim != null && anim.mHeadAnimator != null)
            {
                if (mouthAnimMapper.ContainsKey(anim.mHeadAnimator))
                {
                    mouthAnimMapper.Remove(anim.mHeadAnimator);
                }
            }
        }
        #endregion

        #region 本地仓库获取数据
        /// <summary>
        /// 根据帧数判断当前是否需要张口说话(每次更新间隔0.033秒,按照每秒30帧,每次采样间隔3帧来计算)
        /// </summary>
        /// <param name="audioEvent"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public int ShouldOpenMouth(string audioEvent, int index)
        {
            if (!IsReady)
                return 0;

            //Profiler.BeginSample("LipSync2");

            string t;
            if (m_AudioMouthDic.TryGetValue(audioEvent, out t))
            {
                if (index >= t.Length)
                    return 0;
                else
                    return t[index] == '1' ? 1 : -1;
            }

            //Profiler.EndSample();

            return 0;
        }

        /// <summary>
        /// 检查是否存在对应的MouthEvent配置
        /// </summary>
        /// <param name="eventName"></param>
        /// <returns></returns>
        public bool CheckMouthEventExist(string eventName)
        {
            if (!IsReady)
            {
                return false;
            }
            if (m_AudioMouthDic.ContainsKey(eventName))
            {
                return true;
            }
            return false;
        }

        #endregion

        #region 对外接口
        
        /// <summary>
        /// 获取和Animator依赖的MouthAnimation组件
        /// </summary>
        /// <param name="mAnim"></param>
        /// <returns></returns>
        public MouthAnimation GetAnimatorRef(Animator mAnim)
        {
            mouthAnimMapper.TryGetValue(mAnim, out MouthAnimation mouth);
            return mouth;
        }

        #endregion

    }
}
